<?php

namespace App\Http\Controllers;

use Exception;
use App\Models\Genre;
use App\Models\Station;
use Illuminate\Http\Request;
use App\Models\Station\Report;
use App\Models\Station\Timing;
use App\Package\Attendance\Time;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Writers\CellWriter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;
use App\Models\Statistical\ProjectDimensionalityPatrolReports;
use App\Models\Statistical\StationDimensionalityPatrolReports;

/**
 * 报岗管理业务逻辑控制器
 *
 * Date: 30/04/2018
 * @author George
 * @package App\Http\Controllers
 */
class StationController extends Controller
{
	/**
	 * 根据项目获取报岗点信息
	 *s
	 * Date: 30/04/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
    public function index(Request $request)
    {
    	$project_id = $request->get('project_id');
    	$paginate = $request->get('paginate', 15);
    	$name = $request->get('name');
    	$query = Station::query()->where('project_id', $project_id);

    	if ($name) {
    		$query->where('name', 'like', "%{$name}%");
		}

    	return success($query->paginate($paginate));
    }

	/**
	 * 创建报岗的岗位信息
	 *
	 * Date: 30/04/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
    public function store(Request $request)
    {
    	$attributes = $this->validate($request, [
    		'project_id' => 'required',
    		'name' => 'required',
    		'assignment' => 'nullable'
		]);

    	$attributes['company_id'] = Auth::user()->company_id;

    	$station = Station::create($attributes);
    	return stored($station);
    }

	/**
	 * 获取报岗点详情
	 *
	 * Date: 17/05/2018
	 * @author George
	 * @param Station $station
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
    public function show(Station $station, Request $request)
    {
    	$date = $request->get('date', date('Y-m-d'));

    	$station->schedules = $station->schedules()
			->select(['id', 'time', 'delayed', 'genre_id'])->with(['genre' => function ($query) {
				/**
				 * @var Builder $query
				 */
				$query->select(['id', 'code', 'name']);
			}, 'report' => function ($query) use ($date) {
				/**
				 * @var Builder $query
				 */
				$query->select(['id', 'timing_id', 'created_at', 'address'])->whereDate('created_at', $date);
			}])->get();
    	return success($station);
    }

	/**
	 * 更新报岗点信息
	 *
	 * Date: 30/04/2018
	 * @author George
	 * @param Request $request
	 * @param Station $station
	 * @return \Illuminate\Http\JsonResponse
	 */
    public function update(Request $request, Station $station)
    {
		$attributes = $this->validate($request, [
			'name' => 'required',
			'assignment' => 'nullable'
		]);

		$station->update($attributes);
		return updated($station);
    }

	/**
	 * 删除报岗点
	 *
	 * Date: 30/04/2018
	 * @author George
	 * @param Station $station
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Exception
	 */
    public function destroy(Station $station)
    {
    	$station->delete();
    	return deleted();
    }

	/**
	 * 创建报岗计划
	 *
	 * Date: 01/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function schedule(Request $request)
	{
		$attributes = $this->validate($request, [
			'project_id' => 'required|integer',
			'station_id' => 'required|integer',
			'genre_id' => 'required|integer',
			'times' => 'required|array',
			'delayed' => 'required|integer'
		]);

		$times = array_pull($attributes, 'times');

		$schedules = [];

		try {
			DB::beginTransaction();
			foreach ($times as $time) {
				$schedules[] = Timing::create([
					'project_id' => $attributes['project_id'],
					'station_id' => $attributes['station_id'],
					'genre_id' => $attributes['genre_id'],
					'delayed' => $attributes['delayed'],
					'time' => $time
				]);
			}
			DB::commit();
			return stored($schedules);
		} catch (Exception $exception) {
			DB::rollBack();
			return internalError('创建失败');
		}
    }

	/**
	 * 获取岗位报岗时间设置数据集合
	 *
	 * Date: 12/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function schedules(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required'
		]);
		$project_id = $request->get('project_id');
		$paginate = $request->get('paginate', 15);
		$schedules = DB::table('stations')->select([
			'stations.id as station_id', 'stations.name as station_name', 'genres.id as genres_id', 'genres.name as genre_name'
		])
			->leftJoin('timings', 'stations.id', '=', 'timings.station_id')
			->leftJoin('genres', 'timings.genre_id', '=', 'genres.id')
			->where('timings.project_id', $project_id)
			->groupBy('stations.id', 'genres.id');
		return success($schedules->paginate($paginate));
    }

	/**
	 * 获取时间列表
	 *
	 * Date: 12/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function timings(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'station_id' => 'required',
			'genre_id' => 'required',
		]);

		$project_id = $request->get('project_id');
		$station_id = $request->get('station_id');
		$genre_id = $request->get('genre_id');

		$genre = Genre::query()->select('name', 'start', 'end')->findOrFail($genre_id);

		$timings = DB::table('timings')->select(['id', 'time', 'delayed'])
			->where('project_id', $project_id)
			->where('station_id', $station_id)
			->where('genre_id', $genre_id)
			->orderBy('order')->get();

		$setting = [
			'station_id' => $request->get('station_id'),
			'station_name' => Station::query()->select('name')->findOrFail($station_id)->name,
			'genre_id' => $request->get('genre_id'),
			'genre_name' => $genre->name,
			'genre_start' => $genre->start,
			'genre_end' => $genre->end,
			'delayed' => $timings->first()->delayed,
			'timings' => $timings
		];

		return success($setting);
    }

	/**
	 * 修改岗位时间点
	 *
	 * Date: 18/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \App\Exceptions\GeneralException
	 */
	public function modifySchedule(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'station_id' => 'required',
			'genre_id' => 'required',
			'delayed' => 'required',
			'timings' => 'required|array',
			'deleted' => 'nullable|array',
		]);

		$deleted = $request->get('deleted', []);
		$timings = $request->get('timings');

		/**
		 * @var Genre $genre
		 */
		$genre = Genre::findOrFail($request->get('genre_id'));

		// 验证时间点是否规范
		Time::validateTimings($genre->start, $genre->end, $timings, $request->get('delayed'));

		try {
			DB::beginTransaction();
			if (count($deleted) > 0) {
				DB::table('timings')->whereIn('id', $deleted)->delete();
			}

			$response = [];

			if ($timings && count($timings) > 0) {
				foreach ($timings as $index => $timing) {
					/**
					 * 判断时间点是否存在ID，如果有则更新属性
					 * 如果没有ID，则创建时间点
					 */
					if (array_get($timing, 'id')) {
						$attribute = [
							'project_id' => $request->get('project_id'),
							'station_id' => $request->get('station_id'),
							'genre_id' => $request->get('genre_id'),
							'time' => $timing['time'],
							'delayed' => $request->get('delayed'),
							'order' => $index
						];
						// 更新时间节点属性
						DB::table('timings')->where('id', $timing['id'])->update($attribute);
						$response['updated'][] = $attribute;
					} else {
						// 创建时间节点
						$response['created'][] = Timing::create([
							'project_id' => $request->get('project_id'),
							'station_id' => $request->get('station_id'),
							'genre_id' => $request->get('genre_id'),
							'time' => $timing['time'],
							'delayed' => $request->get('delayed'),
							'order' => $index
						]);
					}
				}
			}
			DB::commit();
			return success($response);
		} catch (Exception $exception) {
			DB::rollBack();
			Log::error($exception->getMessage());
			return internalError('更新岗位设置失败');
		}
	}

	/**
	 * 项目纬度数报表
	 *
	 * Date: 09/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function projectDimensionalityReports(Request $request)
	{
		$start = $request->get('start');
		$end = $request->get('end');
		$export = $request->get('export');
		$project_name = $request->get('project_name');
		$project_id = $request->get('project_id');
		$paginate = $request->get('paginate', 15);

		$query = ProjectDimensionalityPatrolReports::query()->where('company_id', Auth::user()->company_id);

		if ($start && $end) {
			$query->whereBetween('date', [$start, $end]);
		}

		if ($project_id) {
			$query->where('project_id', $project_id);
		}

		if ($project_name) {
			$query->where('project_name', 'like', "%{$project_name}%");
		}

		/**
		 * 导出数据
		 */
		if ($export) {
			Excel::create('users', function ($excel) use ($query) {
				/**
				 * @var LaravelExcelWriter $excel
				 */
				$excel->sheet('项目列表', function($sheet) use ($query) {
					/**
					 * 设置列宽度
					 * @var LaravelExcelWorksheet $sheet
					 */
					$sheet->setWidth([
						'A' => 25,
						'B' => 10,
						'C' => 20,
						'D' => 20,
						'E' => 10,
						'F' => 15
					]);

					/**
					 * 设置对其方式
					 */
					$sheet->cells('A:F', function($cells) {
						/**
						 * @var CellWriter $cells
						 */
						$cells->setAlignment('center');
					});

					$sheet->fromArray($query->get()->map(function ($item) {
						return [
							'项目名称'=> $item->project_name,
							'应报岗次数' => $item->timings_count,
							'实际报岗次数' => $item->actual_quantity,
							'未报岗次数' => $item->unreport_count,
							'完成率' => $item->finish_rate,
							'日期' => $item->date,
						];
					}));
				});
			})->download('xlsx');
		}

		return success($query->paginate($paginate));
    }

	/**
	 * 获取岗位纬度数据报表
	 *
	 * Date: 09/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function stationDimensionalityReports(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'date' => 'required',
		]);

		$project_id = $request->get('project_id');
		$date = $request->get('date');
		$station_name = $request->get('station_name');
		$genre_name = $request->get('genre_name');
		$paginate = $request->get('paginate', 15);

		$query = StationDimensionalityPatrolReports::query()
			->where('company_id', Auth::user()->company_id)
			->where('project_id', $project_id)
			->where('date', $date);

		if ($station_name) {
			$query->where('station_name', $station_name);
		}

		if ($genre_name) {
			$query->where('genre_name', $genre_name);
		}

		return success($query->paginate($paginate));
    }

	/**
	 * 日期维度报表
	 *
	 * Date: 09/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
	 */
	public function timeDimensionalityReports(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'date' => 'required',
			'station_id' => 'required'
		]);
		$project_id = $request->get('project_id');
		$date = $request->get('date');
		$genre_name = $request->get('genre_name');
		$station_id = $request->get('station_id');
		$paginate = $request->get('paginate', 15);

		$query = DB::table('timings')->select([
			'timings.id as timing_id', 'timings.time', 'genres.name as genre_name',
			'reports.user_name', 'reports.project_id', 'reports.station_id', 'reports.address', 'reports.id as report_id', 'reports.created_at'
		])
			->where('reports.project_id', $project_id)
			->where('reports.station_id', $station_id)
			->leftJoin('genres', 'timings.genre_id', '=', 'genres.id')
			->leftJoin('reports', function ($join) use ($date) {
				/**
				 * @var JoinClause $join
				 */
				$join->on('timings.id', '=', 'reports.timing_id')->whereDate('reports.created_at', $date);
			});

		if ($genre_name) {
			$query->where('genres.name', $genre_name);
		}
		return success($query->paginate($paginate));
    }

	/**
	 * 报岗记录详情
	 *
	 * Date: 2018/5/24
	 * @author George
	 * @param Request $request
	 * @param Report $report
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function details(Request $request, Report $report)
	{
		$report->station = $report->station()->first();
		$report->user = $report->user()->first();
		return success($report);
    }
}
